﻿using System;
using System.Linq;
using CardPlay.Model.ActionModel;
using CardPlay.Model.CardModel;
using CardPlay.Model.GameModel;
using CardPlay.Model.GameModel.Actions;
using CardPlay.Model.GameModel.Presentation;
using CardPlay.Model.Layout;

namespace CardPlay.DemoPack.Games
{
    [Game("80782291-1196-47AD-B240-3B380C7E06AC", LevelOfDifficulty.Hard, LevelOfSkill.MostlySkill, DurationOfPlay.MoreThan10Minutes, NumberOfDecks = 2, Family = SpiderVariants.Spiderette.FamilyName)]
    public class RougeEtNoir : StandardCardGame
    {
        public RougeEtNoir()
        {
            MaximumDeals = 1;
            TotalDecks = 2;
            TotalTableaus = 10;
            TotalFoundations = 8;
            TableauBuildSequence = CardFaceSequence.AlternatingColorDescendingRank;
        }

        public override ILayoutSite CreatePresentation(IPresentationContext presentation)
        {
            var foundations = presentation.CreateRowLayout(HorizontalAlignment.Center);
            var foundationStyle = StandardStyles.Foundation;

            foundationStyle.UpdateBaseCues = (pile, cues) => { cues.Rank = Rank.Ace; };
            presentation.AddPiles(foundations, NamesOfFoundations.Take(4), foundationStyle);

            foundationStyle.UpdateBaseCues = (pile, cues) => { cues.Rank = Rank.King; };
            presentation.AddPiles(foundations, NamesOfFoundations.Skip(4), foundationStyle);

            var tableau = presentation.CreateRowLayout();
            var tableauStyle = StandardStyles.Tableau;

            tableauStyle.UpdateBaseCues = (pile, cues) => { cues.Rank = Rank.King; };
            presentation.AddPiles(tableau, NamesOfTableaus, tableauStyle);

            var root = new GridLayout
            {
                Columns = 3,
                Rows = 2,
                HorizontalContentAlignment = HorizontalAlignment.Center,
                VerticalContentAlignment = VerticalAlignment.Stretch
            };

            root.Add(presentation.CreatePileVisual(Stock, presentation.StyleForStock(this)));
            root.Add(presentation.CreateMimimalSpacer());
            root.Add(foundations);

            root.Add(presentation.CreateMimimalSpacer());
            root.Add(presentation.CreateMimimalSpacer());
            root.Add(tableau);

            return root;
        }

        protected override void PrepareDealScript(DealScript script)
        {
            const string prefix = StandardPileNames.PrefixForTableau;

            script.DealCardTo(prefix + 9);

            for (var i = 0; i < 8; ++i)
                script.Deal(String.Join(String.Empty, Enumerable.Repeat("down;", 7 - i)) + "up").To(prefix + (i + 1));

            script.DealRemainingFaceDownTo(Stock);
        }

        protected override IAction QueryActionAt(PartLocation location)
        {
            var card = CardAt(location);
            if (card == null) return null;

            return location.Matches(Stock) && location.Index == this[Stock].TopIndex
                ? new DealOutTableauAction(this, location)
                : base.QueryActionAt(location);
        }

        protected override bool AllowedToPickupAtTableau(RemovePileAction action)
        {
            return action.IsActingOnFaceUpTopCard() || action.IsActingOnFaceUpTopPileInSequence(TableauBuildSequence);
        }

        protected override bool AllowedToBuildFoundation(MovePileAction action)
        {
            if (action.TargetPile.Count == CardFace.RanksPerSuit) return false;

            return action.TargetPile.Location.Matches(StandardPileNames.RangePatternForFoundations(1, 4))
                ? action.IsMovingSingleCard() && action.IsBuildingSameColorAscendingRank()
                : action.PileBeingMoved.Count == CardFace.RanksPerSuit && 
                  action.PileBeingMoved.BottomCard.Rank == Rank.King && 
                  action.PileBeingMoved.IsInSequence(CardFaceSequence.AlternatingColorDescendingRank);
        }

        protected override bool AllowedToBuildEmptyTableau(MovePileAction action)
        {
            return action.PileBeingMoved.BottomCard.Rank == Rank.King;
        }

        protected override bool AllowedToBuildNonEmptyTableau(MovePileAction action)
        {
            return action.TargetPile.TopCard.Rank != Rank.Ace && action.IsBuildingAlternatingColorDescendingRank();
        }

        protected override void OnTransactionEnding()
        {
            this.FlipFaceDownTopCardsInPilesMatching(AnyTableau);
        }
    }
}